package com.meis.widget.corners;


import com.meis.widget.gif.GifDecoder;
import com.meis.widget.utils.AttrUtils;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Image;
import ohos.app.Context;
import ohos.global.resource.*;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.utils.net.Uri;

import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CornersGifView extends Image {
    Context mContext;
    private List<PixelMap> pixelMapList = new ArrayList<>();
    // 动画
    private AnimatorValue animatorValue;
    private ImageSource imageSource;
    private GifDecoder gifDecoder;
    private Boolean ispaused = false;
    private int duration;
    private float speed = 1;
    private int i;
    private float mCornerSize;
    private float mLeftBottomCorner;
    private float mLeftTopCorner;
    private float mRightBottomCorner;
    private float mRightTopCorner;
    // corners array
    private float[] mCorners;
    // 动画侦听函数
    private final AnimatorValue.ValueUpdateListener mAnimatorUpdateListener = (animatorValue, v) -> {
        int size = pixelMapList.size();
        if (size == 0) return;
        int position;
        if (((int) v * size) == size) {
            position = size - 1;
        } else {
            position = (int) (v * size);
        }
        setPixelMap(pixelMapList.get(position));
        invalidate();
    };

    public CornersGifView(Context context) {
        super(context);
        mContext = context;
        gifDecoder = new GifDecoder();
    }

    public CornersGifView(Context context, AttrSet attrs) throws IOException, NotExistException, WrongTypeException {
        super(context, attrs);
        mContext = context;
        gifDecoder = new GifDecoder();
        ResourceManager resourceManager = context.getResourceManager();
        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        sourceOptions.formatHint = "image/gif";
        mCornerSize = AttrUtils.getDimensionFromAttr(attrs, "cornerSize", 0);
        mLeftBottomCorner = AttrUtils.getDimensionFromAttr(attrs, "leftBottomCorner", 0);
        mLeftTopCorner = AttrUtils.getDimensionFromAttr(attrs, "leftTopCorner", 0);
        mRightBottomCorner = AttrUtils.getDimensionFromAttr(attrs, "rightBottomCorner", 0);
        mRightTopCorner = AttrUtils.getDimensionFromAttr(attrs, "rightTopCorner", 0);
        if (mCornerSize == 0) {
            mCorners = new float[]{
                    mLeftTopCorner, mLeftTopCorner,
                    mRightTopCorner, mRightTopCorner,
                    mRightBottomCorner, mRightBottomCorner,
                    mLeftBottomCorner, mLeftBottomCorner};
        } else {
            mLeftTopCorner = mCornerSize;
            mLeftBottomCorner = mCornerSize;
            mRightTopCorner = mCornerSize;
            mRightBottomCorner = mCornerSize;
            mCorners = new float[]{
                    mCornerSize, mCornerSize,
                    mCornerSize, mCornerSize,
                    mCornerSize, mCornerSize,
                    mCornerSize, mCornerSize};
        }

        if (attrs.getAttr("image_src").isPresent()) {
            String id = attrs.getAttr("image_src").get().getStringValue();
            Pattern pattern = Pattern.compile("[^0-9]");
            Matcher matcher = pattern.matcher(id);
            String all = matcher.replaceAll("");
            RawFileEntry rawFileEntry =
                    resourceManager.getRawFileEntry(resourceManager.getMediaPath(Integer.parseInt(all)));
            ImageSource imageSource = ImageSource.create(rawFileEntry.openRawFile(), sourceOptions);
            gifDecoder.read(rawFileEntry.openRawFile(), (int) rawFileEntry.openRawFileDescriptor().getFileSize());
            if (imageSource != null) {
                init(imageSource);
            }
        } else {
            invalidate();
        }
        setCornerRadii(mCorners);
    }

    public CornersGifView(Context context, int resId) throws NotExistException, WrongTypeException, IOException {
        super(context);
        mContext = context;
        gifDecoder = new GifDecoder();
        ResourceManager manager = context.getResourceManager();
        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        sourceOptions.formatHint = "image/gif";
        RawFileEntry rawFileEntry = manager.getRawFileEntry(manager.getMediaPath(resId));
        ImageSource imageSource = ImageSource.create(rawFileEntry.openRawFile(), sourceOptions);
        gifDecoder.read(rawFileEntry.openRawFile(), (int) rawFileEntry.openRawFileDescriptor().getFileSize());
        if (imageSource != null) {
            init(imageSource);
        }
    }

    public CornersGifView(Context context, ImageSource imageSource) {
        this(context);
        load(imageSource);
    }

    public CornersGifView(Context context, InputStream inputStream) {
        this(context);
        load(inputStream);
    }

    public CornersGifView(Context context, File file) {
        this(context);
        load(file);
    }

    public CornersGifView(Context context, Uri contentUri) {
        this(context);
        load(contentUri);
    }

    public CornersGifView(Context context, byte[] data) {
        this(context);
        load(data);
    }

    public CornersGifView(Context context, String path) {
        this(context);
        try {
            load(path);
        } catch (IOException ignored) {
        }
    }

    /**
     * 设置速度
     *
     * @param speed1 速度
     * @return Gif
     */
    public CornersGifView setSpeed(float speed1) {
        float EPSINON = (float) 0.00001;
        if (speed1 > EPSINON) {
            this.speed = speed1;
        }
        animatorValue.stop();
        animatorValue.setDuration((long) (speed * duration));
        animatorValue.start();
        invalidate();
        return this;
    }

    private void init(ImageSource imageSource) {
        pixelMapList.clear();
        duration = 0;
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        decodingOptions.allowPartialImage = true;
        i = 0;
        if (gifDecoder.getFrameCount() > 0) {
            while (i < gifDecoder.getFrameCount()) {
                pixelMapList.add(imageSource.createPixelmap(i, decodingOptions));
                duration += gifDecoder.getDelay(i);
                i++;
            }
        } else {
            try {
                while (imageSource.createPixelmap(i, decodingOptions) != null) {
                    pixelMapList.add(imageSource.createPixelmap(i, decodingOptions));
                    duration += 30;
                    i++;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 启动动画
        animatorValue = new AnimatorValue();
        animatorValue.setCurveType(Animator.CurveType.LINEAR);
        animatorValue.setDelay(100);
        animatorValue.setLoopedCount(Animator.INFINITE);
        animatorValue.setDuration(duration == 0 ? 3000 : duration);
        animatorValue.setValueUpdateListener(mAnimatorUpdateListener);
        animatorValue.start();
    }

    /**
     * 加载 InputStream
     *
     * @param is 输入流
     */
    public void load(InputStream is) {
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        imageSource = ImageSource.create(is, sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 加载 data byte
     *
     * @param data byte[]
     */
    public void load(byte[] data) {
        gifDecoder.read(data);
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        imageSource = ImageSource.create(data, sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 加载   data ByteBuffer
     *
     * @param data ByteBuffer
     */
    public void load(ByteBuffer data) {
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        imageSource = ImageSource.create(data, sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 加载 Callable<RawFileDescriptor>
     *
     * @param callable Callable<RawFileDescriptor>
     */
    public void load(Callable<RawFileDescriptor> callable) {
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        imageSource = ImageSource.create(callable, sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 加载  File
     *
     * @param file 文件
     */
    public void load(File file) {
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        imageSource = ImageSource.create(file, sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 加载 FileDescriptor
     *
     * @param fd FileDescriptor
     */
    public void load(FileDescriptor fd) {
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        imageSource = ImageSource.create(fd, sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 加载 pathName
     *
     * @param pathName 地址
     * @throws IOException
     */
    public void load(String pathName) throws IOException {
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        ResourceManager manager = mContext.getResourceManager();
        RawFileEntry rawFileEntry = manager.getRawFileEntry(pathName);
        imageSource = ImageSource.create(rawFileEntry.openRawFile(), sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 加载 rawFileEntry
     *
     * @param rawFileEntry 资源文件
     * @throws IOException 异常
     */
    public void load(RawFileEntry rawFileEntry) throws IOException {
        gifDecoder.read(rawFileEntry.openRawFile(), (int) rawFileEntry.openRawFileDescriptor().getFileSize());
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        imageSource = ImageSource.create(rawFileEntry.openRawFile(), sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    public void load(ImageSource imageSource) {
        this.imageSource = imageSource;
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 加载 Uri
     *
     * @param uri uri地址
     */
    public void load(Uri uri) {
        ImageSource.SourceOptions sourceOption = new ImageSource.SourceOptions();
        imageSource = ImageSource.create(uri.getDecodedPath(), sourceOption);
        if (imageSource != null) {
            init(imageSource);
        }
    }

    /**
     * 暂停
     */
    public void pause() {
        if (!ispaused) {
            ispaused = true;
        }
        animatorValue.pause();
        invalidate();
    }

    /**
     * 开始
     */
    public void play() {
        if (ispaused) {
            ispaused = false;
        }
        animatorValue.start();
    }

    /**
     * 获取持续时间
     *
     * @return 获取持续时间
     */
    public int getDuration() {
        return duration;
    }

    /**
     * 是否开始
     *
     * @return 是否开始
     */
    public Boolean isInPlaying() {
        return !ispaused;
    }

    /**
     * 重置
     */
    public void reset() {
        animatorValue.stop();
        animatorValue.start();
        invalidate();
    }

    /**
     * 是否循环
     *
     * @return 是否循环
     */
    public boolean isRecycled() {
        return imageSource == null;
    }

    /**
     * 回收
     */
    public void recycle() {
        imageSource = null;
    }

    public ImageSource getImageSource() {
        return imageSource;
    }
    private void setCornerSize(float leftTop, float leftBottom, float rightTop, float rightBottom) {
        mCorners = new float[]{
                leftTop, leftTop,
                rightTop, rightTop,
                rightBottom, rightBottom,
                leftBottom, leftBottom};
        setCornerRadii(mCorners);
        invalidate();
    }

    public float getCornerSize() {
        return mCornerSize;
    }

    public void setCornerSize(float cornerSize) {
        mCornerSize = cornerSize;
        mLeftTopCorner = mCornerSize;
        mLeftBottomCorner = mCornerSize;
        mRightTopCorner = mCornerSize;
        mRightBottomCorner = mCornerSize;
        setCornerSize(cornerSize, cornerSize, cornerSize, cornerSize);
    }

    public float getLeftBottomCorner() {
        return mLeftBottomCorner;
    }

    public void setLeftBottomCorner(float leftBottomCorner) {
        mLeftBottomCorner = leftBottomCorner;
        setCornerSize(mLeftTopCorner, mLeftBottomCorner, mRightTopCorner, mRightBottomCorner);
    }

    public float getLeftTopCorner() {
        return mLeftTopCorner;
    }

    public void setLeftTopCorner(float leftTopCorner) {
        mLeftTopCorner = leftTopCorner;
        setCornerSize(mLeftTopCorner, mLeftBottomCorner, mRightTopCorner, mRightBottomCorner);
    }

    public float getRightBottomCorner() {
        return mRightBottomCorner;
    }

    public void setRightBottomCorner(float rightBottomCorner) {
        mRightBottomCorner = rightBottomCorner;
        setCornerSize(mLeftTopCorner, mLeftBottomCorner, mRightTopCorner, mRightBottomCorner);
    }

    public float getRightTopCorner() {
        return mRightTopCorner;
    }

    public void setRightTopCorner(float rightTopCorner) {
        mRightTopCorner = rightTopCorner;
        setCornerSize(mLeftTopCorner, mLeftBottomCorner, mRightTopCorner, mRightBottomCorner);
    }
}